const dgram = require('dgram');
const child_process = require('child_process');

class ResPlugin {

  constructor() {
    this.chunkVersions = {};
    this.allChunks = {};
    this.changedChunks = [];

    const server = dgram.createSocket('udp4');
    server.on('message', (msg, rinfo) => {
      console.log(`ResPlugin: ${msg} from ${rinfo.address}:${rinfo.port}`);
      let data = JSON.parse(msg),
        message;
      switch (data.cmd) {
      case 'GET_CHANGE_CHUANKS':
        let changedFiles = this.changedChunks.reduce((list, chunk) => list.concat(chunk.files), []);
        message = Buffer.from(JSON.stringify({ cmd: data.cmd, res: changedFiles }));
        server.send(message, rinfo.port, rinfo.address);
        break;
      case 'REST_CHANGE_CHUANKS':
        this.changedChunks = [];
        message = Buffer.from(JSON.stringify({ cmd: data.cmd }));
        server.send(message, rinfo.port, rinfo.address);
        break;
      case 'GET_ALL_CHUANKS':
        let allFiles = this.allChunks.reduce((list, chunk) => list.concat(chunk.files), []);
        message = Buffer.from(JSON.stringify({ cmd: data.cmd, res: allFiles }));
        server.send(message, rinfo.port, rinfo.address);
        break;
      }
    });
    server.bind(53216);
  }


  apply(compiler) {
    this.compiler = compiler;

    compiler.hooks.afterEmit.tap('ResPlugin', (compilation, callback) => {
      const { inputFileSystem, outputFileSystem, outputPath } = compiler;
      this.compilation = compilation;
      if (compiler.options.devServer && compiler.options.devServer.outputPath) {
        outputPath = compiler.options.devServer.outputPath;
      }
      this.allChunks = compilation.chunks;

      compilation.chunks.forEach(function(chunk, index) {
        chunk.files.forEach(function(filename, index) {
          // console.log('filename:', filename);
          // let source = compilation.assets[filename].source();
        });
      });
    });

    let change_names = [];
    compiler.hooks.emit.tapAsync('ResPlugin', (compilation, callback) => {
      let changedChunks = compilation.chunks.filter((chunk) => {
        let oldVersion = this.chunkVersions[chunk.name];
        this.chunkVersions[chunk.name] = chunk.hash;
        if (chunk.hash !== oldVersion && !change_names.includes(chunk.name)) {
          change_names.push(chunk.name);
          this.changedChunks.push(chunk);
          return true;
        }
        return false;
      });
      callback();
    });

  }

}

module.exports = ResPlugin;
